package com.huatai.datadevelop.thread.task;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.huatai.datadevelop.constant.Constant;
import com.huatai.datadevelop.entity.ApiSuperviseEntity;
import com.huatai.datadevelop.entity.TableManageEntity;
import com.huatai.datadevelop.service.ApiSuperviseService;
import com.huatai.datadevelop.service.TemplateService;
import com.huatai.datadevelop.service.TokenConfigService;
import com.huatai.datadevelop.thread.service.InsertDataBaseExecutor;
import com.huatai.datadevelop.utils.InitHashMapUtil;
import com.huatai.datadevelop.utils.JDBCUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.sql.*;
import java.util.*;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @author hecai
 * @description: TODO
 * @date 2022/12/19 10:59
 * @Version 1.0
 */
@Service
@Slf4j
public class ExecutService extends TemplateService {
    @Autowired
    private TokenConfigService tokenConfigService;
    @Autowired
    private InsertDataBaseExecutor insertDataBaseExecutor;
    @Autowired
    private ApiSuperviseService apiSuperviseService;

    /**
     * 获取第三方接口数据
     */
    public void asyncRequestApi(TableManageEntity apiManageEntity) {
        String type = "定时数据采集";
        ApiSuperviseEntity apiSuperviseEntity = new ApiSuperviseEntity();
        try{
            ApiSuperviseEntity interface_name = this.apiSuperviseService.getOne(new QueryWrapper<ApiSuperviseEntity>()
                    .eq("interface_name", apiManageEntity.getTableName())
                    .eq("type",type));
            if(interface_name!=null){
                apiSuperviseEntity = interface_name;
            }
        }catch (Exception ex){}

        apiSuperviseEntity.setType(type);
        apiSuperviseEntity.setInterfaceName(apiManageEntity.getTableName());
        apiSuperviseEntity.setName(apiManageEntity.getName());
        apiSuperviseEntity.setUrl(apiManageEntity.getUrl());
        apiSuperviseEntity.setSuperviseTime(new Date());

        String method = apiManageEntity.getMethod();
        String heard = apiManageEntity.getHearder();
        Map<String, String> heardMap = new ConcurrentHashMap<String,String>();
        if(StringUtils.isNotBlank(heard)){
            heardMap = JSON.parseObject(heard, HashMap.class);
        }else {
            heardMap = InitHashMapUtil.InitHashMapJSON();
        }
        try{
            if(method.equalsIgnoreCase("GET")){
                this.getGetRequestData(apiManageEntity,heardMap);
            }else {
                 this.getPostRequestData(apiManageEntity,heardMap);
            }
        }catch (Exception ex){
            log.error("处理数据报错");
            apiSuperviseEntity.setStatus(Constant.ABNORMAL);
            apiSuperviseEntity.setReason(ex.getMessage());
        }
        this.apiSuperviseService.executorService(apiSuperviseEntity);
    }

    /**
     * 获取post请求参数配置
     * @param data
     * @param apiManageEntity
     * @return
     */
    public void getPostRequestData(TableManageEntity apiManageEntity, Map<String, String> heardMap) {
        String body = apiManageEntity.getBody();
        Map<String,Object> mapData = new HashMap<>();
        if (StringUtils.isNotBlank(body)) {
            mapData = JSON.parseObject(body);
        }
        this.getCommonRequest(mapData,apiManageEntity,heardMap,apiManageEntity.getMethod());
    }

    /**
     * 获取get请求参数配置
     * @param data
     * @param apiManageEntity
     * @return
     */
    public void getGetRequestData(TableManageEntity apiManageEntity, Map<String, String> heardMap) {
        //TODO 后续需要处理的get逻辑放置在此处
        //get请求参数配置
        String param = "";
        StringBuilder stringBuilder = new StringBuilder();
        String body = apiManageEntity.getBody();
        Map<String,Object> data = new HashMap<>();
        if(StringUtils.isNotBlank(body)){
            data = JSON.parseObject(body, HashMap.class);
        }
        for (Map.Entry<String,Object> map:data.entrySet()){
            String key = map.getKey();
            Object value = map.getValue();
            stringBuilder.append(key).append("=").append(value).append("&");
        }
        param = param + stringBuilder.toString();
        if(StringUtils.isNotBlank(param)){
            param = param.substring(0,param.length()-1);
            apiManageEntity.setUrl(apiManageEntity.getUrl() + "?" + param);
        }
        this.getCommonRequest(data,apiManageEntity,heardMap,"GET");
    }

    /**
     * 数据统一出口
     * @param data
     * @param apiManageEntity
     * @param heardMap
     * @param token
     * @param method
     * @return
     */
    public void getCommonRequest(Map<String,Object> data, TableManageEntity apiManageEntity, Map<String, String> heardMap,String method){
        //判断是否需要token
        String needToken = apiManageEntity.getNeedToken();
        if(needToken.equalsIgnoreCase(Constant.TRUE)){
            String token = apiManageEntity.getTokenPrefix() + this.tokenConfigService.getApiTokenByBody(apiManageEntity.getTokenId());
            String tokenPath = apiManageEntity.getTokenPath();
            String tokenData = apiManageEntity.getTokenData();
            //TODO 处理token
            switch (tokenPath) {
                case "heard":
                    heardMap.put(tokenData, token);
                    break;
                case "body":
                    data.put(tokenData, token);
                    break;
                case "param":
                    String param = tokenData + "=" + token;
                    if(apiManageEntity.getUrl().contains("?")){
                        apiManageEntity.setUrl(apiManageEntity.getUrl() + param);
                    }else {
                        apiManageEntity.setUrl(apiManageEntity.getUrl() +"?"+ param);
                    }
                    break;
            }
        }

        //TODO 第一次请求获取到数据总条数
        Object object= method.equalsIgnoreCase("GET")?
                this.get(apiManageEntity.getUrl(),heardMap,Object.class)
                :
                this.postByModelExchange(apiManageEntity.getUrl(), heardMap, data, Object.class);

        List<String> dataPathList = new ArrayList<>();
        String dataPath = apiManageEntity.getDataPath();
        String[] split = dataPath.split("\\.");
        for (String str : split) {
            dataPathList.add(str);
        }

        String updateType = apiManageEntity.getUpdateType();
        String tableName = apiManageEntity.getTableName();
        String updateColumnName = "";
        List<String> newestDataByColumn = new ArrayList<>();
        //全量删除
        if (updateType.equalsIgnoreCase("allDelete")) {
            //delete from 表名;
            String deleteSQL = "delete from " + tableName;
            executeDeleteTable(deleteSQL);
        } else {
            //若是增量更新，字段必须是：increment,字段名称
            String[] splitUpdateType = updateType.split(",");
            updateColumnName = splitUpdateType[1];
            String sql = "select " + updateColumnName+ " from " + tableName +" order by "+ updateColumnName+" desc limit 1;";
            newestDataByColumn = getNewestDataByColumn(sql,updateColumnName);
        }

        //分页参数
        String pageData = apiManageEntity.getPageData();
        if(StringUtils.isNotBlank(pageData)){
            String limit = "";
            String pageStr = "";
            List<String> totlePathList = new CopyOnWriteArrayList<String>();
            String totlePath = apiManageEntity.getTotalPath();
            String[] titleSplit = totlePath.split("\\.");
            for (String str : titleSplit) {
                totlePathList.add(str);
            }
            //获取到数据总条数
            Integer totleNumber = (Integer)this.recursionFetchData(object, totlePathList);
            //每一页数据条数
            Integer defaultPageCount = apiManageEntity.getDefaultPageCount();
            if(defaultPageCount==null || defaultPageCount==0){
                defaultPageCount = 1000;
            }
            //共有多少页
            int pageSizeCount = totleNumber/defaultPageCount + 1;
            String[] pageDataSpilt = pageData.split(",");
            limit = pageDataSpilt[0];
            pageStr = pageDataSpilt[1];
            String url = apiManageEntity.getUrl();
            //遍历每一页数据入库
            for (int i = 1; i <= pageSizeCount; i++) {
                //修复
                apiManageEntity.setUrl(url);
                Object fetchData = null;
                //起始页数据
                int start = i;
                //get请求的分页参数放置在url后面
                if(apiManageEntity.getMethod().equalsIgnoreCase("GET")){
                    String temp = limit + "=" +start + "&" + pageStr + "=" + defaultPageCount;
                    if(apiManageEntity.getUrl().contains("?")){
                        apiManageEntity.setUrl(apiManageEntity.getUrl()+temp);
                    }else {
                        apiManageEntity.setUrl(apiManageEntity.getUrl()+"?"+temp);
                    }
                    fetchData = this.get(apiManageEntity.getUrl(), heardMap, Object.class);
                }else {
                    data.put(limit,start);
                    data.put(pageStr,defaultPageCount);
                    fetchData = this.postByModelExchange(apiManageEntity.getUrl(), heardMap, data, Object.class);
                }
                fetchData = recursionFetchData(fetchData,dataPathList);
                //数据尝试异步入库
                if(fetchData instanceof ArrayList){
                    insertDataBaseExecutor.insertDataArrayList((ArrayList)fetchData,apiManageEntity.getField(),apiManageEntity.getTableName(),updateColumnName,newestDataByColumn);
                }else {
                    insertDataBaseExecutor.insertDataLinkedHashMap(fetchData,apiManageEntity.getField(),apiManageEntity.getTableName());
                }
            }
        }
        else {
            Object fetchData = object;
            fetchData = recursionFetchData(fetchData,dataPathList);
            //数据尝试异步入库
            if(fetchData instanceof ArrayList){
                insertDataBaseExecutor.insertDataArrayList((ArrayList)fetchData,apiManageEntity.getField(),apiManageEntity.getTableName(),updateColumnName,newestDataByColumn);
            }else {
                insertDataBaseExecutor.insertDataLinkedHashMap(fetchData,apiManageEntity.getField(),apiManageEntity.getTableName());
            }
        }
    }

    /**
     * 递归取数据
     *
     * @param object
     * @param path
     * @return
     */
    public Object recursionFetchData(Object object, List<String> path) {
        Object data = null;
        if(object!=null){
            String keyPath = path.get(0);
            data = ((LinkedHashMap) object).get(keyPath);
            if(path.size() != 1){
                path.remove(0);
                return recursionFetchData(data,path);
            }
        }
        return data;
    }

    /**
     * 清空数据库数据
     * 锁机制，避免造成数据混乱
     *
     * @param sql
     */
    private synchronized void executeDeleteTable(String sql) {
        Connection conn = JDBCUtils.getConnection();
        Statement stmt = null;
        try {
            stmt = conn.createStatement();
            int i = stmt.executeUpdate(sql);
            log.info("清空数据成功，共清空了 " + i + "条数据");
        } catch (SQLException e) {
            try {
                conn.rollback();
            } catch (SQLException ex) {}
            log.error("清空数据失败", e.getMessage());
        }finally {
            try {
                if(conn!=null){
                    conn.close();
                }
                if(stmt!=null){
                    stmt.close();
                }
            } catch (SQLException e) {
                log.error("Statement关闭失败");
            }
        }
    }

    /**
     * 获取数据库中最新一条数据
     * @param sql
     * @return
     */
    public List<String> getNewestDataByColumn(String sql,String column){
        Connection conn = JDBCUtils.getConnection();
        PreparedStatement preparedstatement = null;
        ResultSet resultSet = null;
        try {
            preparedstatement = conn.prepareStatement(sql);
            resultSet = preparedstatement.executeQuery();
            List<String> result = new ArrayList<>();
            while (resultSet.next()){
                result.add(resultSet.getString(column));
            }
            return result;
        } catch (SQLException e) {
            log.error("执行查询数据失败，失败原因"+e.getMessage());
        }finally {
            try {
                if(conn!=null){
                    conn.close();
                }
                if(resultSet!=null){
                    resultSet.close();
                }
                if(preparedstatement!=null){
                    preparedstatement.clearParameters();
                    preparedstatement.close();
                }
            } catch (SQLException e) {
                log.error("preparedstatement关闭失败");
            }
        }
        return null;
    }
}
